package com.mandao.oneplat.boot.handler;

import com.mandao.oneplat.boot.OnePlatConfig;
import com.mandao.oneplat.boot.context.OneContext;
import com.mandao.oneplat.boot.context.OneRequest;
import com.mandao.oneplat.boot.context.OneResponse;
import com.mandao.oneplat.boot.mvc.control.EOneCOntrolUriMode;
import com.mandao.oneplat.boot.mvc.view.OneView;
import com.mandao.oneplat.boot.support.IOneCookieName;
import com.mandao.oneplat.boot.support.cache.BlankAssetsException;
import com.mandao.oneplat.boot.support.cache.ICacheAssets;
import com.mandao.oneplat.boot.util.DeviceUtil;
import com.mandao.oneplat.boot.util.UrlUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;

import static io.netty.handler.codec.http.HttpHeaderNames.COOKIE;
import static io.netty.handler.codec.http.HttpMethod.GET;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * Created by sunson on 2017/3/23.
 */
public class OneServerPreHandler extends ChannelInboundHandlerAdapter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private OnePlatConfig oneOption;
    private ICacheAssets cacheAssets;

    public OneServerPreHandler(OnePlatConfig oneOption, ICacheAssets cacheAssets) {
        this.oneOption = oneOption;
        this.cacheAssets = cacheAssets;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof HttpRequest) {
            HttpRequest httpRequest = (HttpRequest) msg;
            // 创建上下文
            OneContext oneContext = new OneContext(httpRequest);

            String uri = httpRequest.uri();
            if (GET != httpRequest.method()) {
                logger.warn("不支持GET以外的请求：{}", uri);
                return;
            }
            // 剔除uri？和#号部分X
            uri = UrlUtil.removeQueryString(uri);
            // 如果是浏览器默认请求的，则不处理
            // 如需设置，则请置于assets目录下
            if (uri.equals("/favicon.ico")) {
                oneContext.getOneResponse().setHttpResponse(OneResponse.BAD_RESPONSE);
                ctx.write(oneContext);
                return;
            }
            OneRequest oneRequest = oneContext.getOneRequest();
            oneRequest.setUri(uri);
            // 解析QueryString的参数
            oneRequest.addParams(resolveParams(oneContext.getHttpRequest()));
            oneRequest.setMobile(DeviceUtil.isMobile(httpRequest));
            oneRequest.setIp(DeviceUtil.getClientIp(ctx, httpRequest));
            oneRequest.setLang(Locale.SIMPLIFIED_CHINESE.toLanguageTag());
            // 处理Cookie部分
            String cookieHeader = httpRequest.headers().get(COOKIE);
            if (StringUtils.isNotEmpty(cookieHeader)) {
                Set<Cookie> cookieSet = ServerCookieDecoder.STRICT.decode(cookieHeader);
                if (cookieSet != null && !cookieSet.isEmpty()) {
                    for (Cookie cookie : cookieSet) {
                        oneRequest.addCookie(cookie.name(), cookie.value());
                    }
                }
                String wlang = oneRequest.getCookie(IOneCookieName.WEB_LANGUAGE);
                if (StringUtils.isNotEmpty(wlang)) {
                    oneRequest.setLang(wlang);
                }
            }

//            if (CollectionUtil.isEmpty(oneRequest.getCookies()) || oneRequest.getCookie(IOneCookieName.SESSION_ID) == null) {
//                // 创建session
//                OneSession oneSession = OneSessionManager.genSession(oneContext);
//                oneContext.setOneSession(oneSession);
//                Cookie cookie = new DefaultCookie(IOneCookieName.SESSION_ID, oneSession.getSid());
//                oneContext.getOneResponse().addCookie(cookie);
//            }

            // 如果是静态资源则直接处理
            if (uri.startsWith(ICacheAssets.ASSETS_DIR)) {
                try {
                    FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(cacheAssets.findAssets(uri)));
                    oneContext.getOneResponse().setHttpResponse(response);
                } catch (IOException e) {
                    oneContext.setOneView(new OneView(EOneCOntrolUriMode.STATIC, uri));
                } catch (BlankAssetsException e) {
                    oneContext.getOneResponse().setHttpResponse(OneResponse.BAD_RESPONSE);
                }

                ctx.write(oneContext);
            } else {
                ctx.fireChannelRead(oneContext);
            }
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }


    /**
     * @param req
     * @return
     */
    Map<String, String> resolveParams(HttpRequest req) {
        final Map<String, String> parmMap = new HashMap<>();
        QueryStringDecoder decoder = new QueryStringDecoder(req.uri(), true);
        decoder.parameters().entrySet().forEach(entry -> {
            List<String> values = entry.getValue();
            parmMap.put(entry.getKey(), (values == null || values.isEmpty()) ? null : values.get(0));
        });
        return parmMap;
    }
}
